#include <QDebug>
#include "WebServer.hpp"

#ifdef _WIN32
#include <windows.h>
#define SLEEP(ms) Sleep(ms)
#endif
#ifdef __linux__
#define SLEEP(ms) usleep(ms*1000)
#endif

extern QByteArray img_buf;
struct mg_serve_http_opts WebServer::opts;
WebServer* WebServer::instanceServe = NULL;



static int has_prefix(const struct mg_str *uri, const struct mg_str *prefix)
{
  return uri->len > prefix->len && memcmp(uri->p, prefix->p, prefix->len) == 0;
}

static int is_equal(const struct mg_str *s1, const struct mg_str *s2)
{
  return s1->len == s2->len && memcmp(s1->p, s2->p, s2->len) == 0;
}

static void handle_sum_call(struct mg_connection *nc, struct http_message *hm)
{
  char n1[100], n2[100];
  double result;

  /* Get form variables */
  mg_get_http_var(&hm->body, "n1", n1, sizeof(n1));
  mg_get_http_var(&hm->body, "n2", n2, sizeof(n2));

  /* Send headers */
  mg_printf(nc, "%s", "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");

  /* Compute the result and send it back as a JSON object */
  result = strtod(n1, NULL) + strtod(n2, NULL);
  mg_printf_http_chunk(nc, "{ \"result\": %lf }", result);
  mg_send_http_chunk(nc, "", 0); /* Send empty chunk, the end of response */
}

WebServer::WebServer()
    :_thrIsRun(false),_thr(NULL),
      _port(8000),_dirList(true)
{
    _root = strdup(".");
}

WebServer::~WebServer()
{
    this->stop();
}


int WebServer::begin_request_handler(struct mg_connection *conn)
{

#if 1
//    mg_printf(conn,
//        "HTTP/1.1 200 OK\r\n"
//        "Content-Type: multipart/x-mixed-replace;boundary=frame\r\n"
//        "Cache-Control: no-store\r\n"
//        "Access-Control-Allow-Origin:*\r\n"
//        "Pragma: no-cache\r\n\r\n");

    mg_printf(conn,
        "HTTP/1.1 200 OK\r\n");
    for(;;)
    {
        if( img_buf.size()<4 ||
            (img_buf[0]!=0xff && img_buf[0]!=0xd8) ||
            (img_buf[img_buf.size()-2]!=0xff && img_buf[img_buf.size()-1]!=0xd9))
        {
            SLEEP(10);
            continue;
        }
        mg_printf(conn,
            "--frame\r\n"
            "Content-Type: image/jpeg\r\n"
            "Content-length: %d\r\n"
            "\r\n",img_buf.size());
       qDebug()<<"get";
       mg_send(conn,img_buf.data(), img_buf.size());
       SLEEP(50);
       break;
    }
    qDebug()<<"send finish!";
#endif
    return 1;
}

//=========================================================

WebServer* WebServer::getInstance()
{
    if(instanceServe == NULL){
        instanceServe = new WebServer;
    }
    return instanceServe;
}


//=========================================================

void WebServer::start()
{
    if(!_thrIsRun){
        _thrIsRun = true;
        if(_thr != NULL){
            delete _thr;
        }
        // 设置线程
        _thr = new std::thread([this](){this->doServerPoll();});
        _thr->detach();
    }
}

void WebServer::stop()
{
    if(_thrIsRun){
        _thrIsRun = false;
    }
    sleep(1);   /// 等待结束
}


void WebServer::reStart()
{
    this->stop();
    this->start();
}


//=========================================================

void WebServer::setDocumentRoot(const char *rootpath)
{
    if(_root != NULL){
        free(_root);
    }
    _root = strdup(rootpath);
}

const char *WebServer::getDocumentRoot()const
{
    return _root;
}

void WebServer::setPort(unsigned short port)
{
    _port = port;
}

unsigned short WebServer::getPort() const
{
    return _port;
}

void WebServer::setEnableDirectoryListing(bool enable)
{
    _dirList = enable;
}

bool WebServer::isEnableDirectoryListing() const
{
    return _dirList;
}

//=========================================================

void WebServer::updateServerParameters()
{
    // 1. 初始化Mgr
    mg_mgr_init(&_mgr,NULL);
    // 2. 绑定
    {
        char buf[16];
        sprintf(buf,"%hu",_port);
        _pnc = mg_bind(&_mgr,buf,WebServer::ev_handler);
    }
    // 3. 设置 HTTP 服务器参数
    {
        mg_set_protocol_http_websocket(_pnc);
        // 设置服务器Web根目录
        opts.document_root = _root;
        // 允许通过WebDAV访问 Allow access via webDav
        opts.dav_document_root = ".";
        // 设置开启目录列表
        opts.enable_directory_listing = _dirList?"yes":"no";
    }
}

//=========================================================

void WebServer::doServerPoll()
{
    puts("start======");
    // 先更新参数
    updateServerParameters();
    // 进行轮询
    while(_thrIsRun){
        // 进行轮询,超时等待1000ms
        mg_mgr_poll(&_mgr,1000);
    }
    // 释放资源
    mg_mgr_free(&_mgr);
    puts("stop======");
}

void WebServer::ev_handler(mg_connection *nc, int ev, void *ev_data)
{

    struct http_message *hm = (struct http_message *) ev_data;

    switch(ev)
    {
        case MG_EV_HTTP_REQUEST:

          if (mg_vcmp(&hm->uri, "/api/v1/sum") == 0)
          {
            qDebug()<<"in api v1 sum";
            handle_sum_call(nc, hm); /* Handle RESTful call */
          }
          else if(mg_vcmp(&hm->uri, "/capture") == 0)
          {
              qDebug()<<"In live url";
              int dd = begin_request_handler(nc);
          }
          else
          {
            mg_serve_http(nc, hm, opts); /* Serve static content */
          }
          break;
        default:
          break;
    }

}
